/**
 * @file common.c
 * Implementation of the utility functions contained in <b>Common<b/> module.
 */

#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>

#include "common.h"

/** 
 * @brief Return the minimum of two integers
 *
 * @param a the first integer
 * @param b the second integer
 *
 * @return the minimum value
 */
int min(int a, int b)
{
	return a < b? a : b;
}

/** 
 * @brief Return the maximum of two integers
 *
 * @param a the first integer
 * @param b the second integer
 *
 * @return the maximum value
 */
int max(int a, int b)
{
	return a > b? a : b;
}

/** 
 * @brief Split a string into tokens
 *
 * @param s the string to split
 * @param tok the address of a an array of strings where to put the tokens
 * @param is_delim() a function which decides if a character should be treated as a delimiter
 * @return the number of tokens found
 *
 * get_tokens splits the given string into tokens without modifying the original string and regardless of the number and/or the length of the tokens. This is achieved by doing multiple passes through the string and dynamically allocating enough memory. For this reason you should use free_tokens() in order to release the allocated memory.
 *
 * @see free_tokens
 */
int get_tokens(const char *s, char ***tok, int (*is_delim)(int))
{
	int T = 0; // number of tokens
	int i, j, k, t;

	/* Do a first pass to determine the number of tokens */
	for(i = 0; s[i]; ) {
		/* Skip delimiters before a token */
		for(; s[i] && is_delim(s[i]); ++i);
		T += (s[i] != 0); // we have a token!
		/* Skip until the next token */
		for(; s[i] && !is_delim(s[i]); ++i);
	}

	/* Avoid allocation if there are no tokens */
	if(T == 0) {
		*tok = NULL; // protect against a future free()
		return 0;
	}

	/* Allocate the array of tokens */
	(*tok) = (char **)malloc(T*sizeof(char *));
	if(*tok == NULL) {
		fprintf(stderr, "%s: %d: get_tokens(): WARNING malloc() failed! Returning no tokens.\n", __FILE__, __LINE__);
		return 0;
	}
	for(t = 0; t < T; ++t)
		(*tok)[t] = NULL;

	/* Do a second pass to extract the tokens */
	for(i = t = 0; t < T; ++t) {
		for(; s[i] && is_delim(s[i]); ++i);
		for(j = i; s[j] && !is_delim(s[j]); ++j);
		(*tok)[t] = (char *)malloc(j-i+1); // \0 at the end

		if((*tok)[t] == NULL) {
			fprintf(stderr, "%s: %d: ERROR malloc() failed! Trying to clear up the mess.\n", __FILE__, __LINE__);
			free_tokens(T, *tok);
			return 0;
		}

		for(k = i; k < j; ++k)
			(*tok)[t][k-i] = s[k];
		(*tok)[t][k-i] = '\0';
		i = j;
	}

	return T;
}

/** 
 * @brief Free an array of strings
 *
 * @param T the number of strings in the array
 * @param tok the array of strings
 *
 * It was designed to free the array of tokens created by get_tokens()
 */
void free_tokens(int T, char **tok)
{
	if(!tok)
		return;
	int i;
	for(i = 0; i < T; ++i) {
		free(tok[i]);
		tok[i] = 0;
	}
	free(tok);
}

void verbose(const Node *node, int level, char *format, ...)
{
	if(node->verbosity < level)
		return;

	/* Indent output */
	/*
	for(int i = 0; i < level; ++i)
		fprintf(stderr, "\t");
	fprintf(stderr, "* ");
	*/

	va_list ap;
	va_start(ap, format);
	vfprintf(stderr, format, ap);
	va_end(ap);
}
